package vip.aster.generator.service.impl;

import cn.hutool.core.text.NamingCase;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.aster.common.exception.BusinessException;
import vip.aster.common.utils.PageInfo;
import vip.aster.generator.query.Query;
import vip.aster.generator.config.DataSourceConfig;
import vip.aster.generator.config.template.GeneratorConfig;
import vip.aster.generator.config.template.GeneratorInfo;
import vip.aster.generator.entity.GenTable;
import vip.aster.generator.entity.GenTableField;
import vip.aster.generator.enums.FormLayoutEnum;
import vip.aster.generator.enums.GeneratorTypeEnum;
import vip.aster.generator.mapper.GenTableMapper;
import vip.aster.generator.service.GenDataSourceService;
import vip.aster.generator.service.GenTableFieldService;
import vip.aster.generator.service.GenTableService;
import vip.aster.generator.utils.GenUtils;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * GenTableServiceImpl
 *
 * @author Aster
 * @since 2024/2/26 10:44
 */
@Service
@AllArgsConstructor
public class GenTableServiceImpl extends ServiceImpl<GenTableMapper, GenTable> implements GenTableService {
    private final GenTableMapper tableMapper;
    private final GenTableFieldService tableFieldService;
    private final GenDataSourceService dataSourceService;
    private final GeneratorConfig generatorConfig;

    @Override
    public PageInfo<GenTable> page(Query query) {
        LambdaQueryWrapper<GenTable> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(query.getTableName()), GenTable::getTableName, query.getTableName());
        Page<GenTable> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<GenTable> pageList = tableMapper.selectPage(page, queryWrapper);

        return new PageInfo<>(pageList.getRecords(), pageList.getTotal());
    }

    @Override
    public GenTable getByTableName(String tableName) {
        LambdaQueryWrapper<GenTable> queryWrapper = Wrappers.lambdaQuery();
        return tableMapper.selectOne(queryWrapper.eq(GenTable::getTableName, tableName));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatchIds(String[] ids) {
        List<String> list = Arrays.stream(ids).toList();
        this.removeBatchByIds(list);
    }

    @Override
    public void tableImport(String datasourceId, String tableName) {
        // 初始化配置信息
        DataSourceConfig dataSource = dataSourceService.get(datasourceId);
        // 查询表是否存在
        GenTable table = this.getByTableName(tableName);
        // 表存在
        if (table != null) {
            throw new BusinessException(tableName + "已存在");
        }

        // 从数据库获取表信息
        table = GenUtils.getTable(dataSource, tableName);

        // 代码生成器信息
        GeneratorInfo generator = generatorConfig.getGeneratorConfig();

        // 保存表信息
        table.setPackageName(generator.getProject().getPackageName());
        table.setVersion(generator.getProject().getVersion());
        table.setBackendPath(generator.getProject().getBackendPath());
        table.setFrontendPath(generator.getProject().getFrontendPath());
        table.setAuthor(generator.getDeveloper().getAuthor());
        table.setEmail(generator.getDeveloper().getEmail());
        table.setFormLayout(FormLayoutEnum.ONE.getValue());
        table.setGeneratorType(GeneratorTypeEnum.ZIP_DOWNLOAD.ordinal());
        table.setClassName(NamingCase.toPascalCase(tableName));
        table.setCreateTime(LocalDateTime.now());

        String moduleSimple = tableName.contains("_") ? tableName.split("_")[0] : tableName;
        String functionName = tableName.contains("_") ? tableName.split("_")[1] : tableName;
        table.setModuleName(moduleSimple);
        table.setModuleSimple(moduleSimple);
        table.setFunctionName(functionName);

        this.save(table);

        // 获取原生字段数据
        List<GenTableField> tableFieldList = GenUtils.getTableFieldList(dataSource, table.getId(), table.getTableName());
        // 初始化字段数据
        tableFieldService.initFieldList(tableFieldList);

        // 保存列数据
        tableFieldList.forEach(tableFieldService::save);

        try {
            //释放数据源
            dataSource.getConnection().close();
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void sync(String id) {
        GenTable table = this.getById(id);

        // 初始化配置信息
        DataSourceConfig datasource = dataSourceService.get(table.getDatasourceId());

        // 从数据库获取表字段列表
        List<GenTableField> dbTableFieldList = GenUtils.getTableFieldList(datasource, table.getId(), table.getTableName());
        if (dbTableFieldList.isEmpty()) {
            throw new BusinessException("同步失败，请检查数据库表：" + table.getTableName());
        }

        List<String> dbTableFieldNameList = dbTableFieldList.stream().map(GenTableField::getFieldName).toList();

        // 表字段列表
        List<GenTableField> tableFieldList = tableFieldService.getByTableId(id);

        Map<String, GenTableField> tableFieldMap = tableFieldList.stream().collect(Collectors.toMap(GenTableField::getFieldName, Function.identity()));

        // 初始化字段数据
        tableFieldService.initFieldList(dbTableFieldList);

        // 同步表结构字段
        dbTableFieldList.forEach(field -> {
            // 新增字段
            if (!tableFieldMap.containsKey(field.getFieldName())) {
                tableFieldService.save(field);
                return;
            }

            // 修改字段
            GenTableField updateField = tableFieldMap.get(field.getFieldName());
            updateField.setPrimaryPk(field.isPrimaryPk());
            updateField.setFieldComment(field.getFieldComment());
            updateField.setFieldType(field.getFieldType());
            updateField.setAttrType(field.getAttrType());

            tableFieldService.updateById(updateField);
        });

        // 删除数据库表中没有的字段
        List<GenTableField> delFieldList = tableFieldList.stream().filter(field -> !dbTableFieldNameList.contains(field.getFieldName())).toList();
        if (!delFieldList.isEmpty()) {
            List<String> fieldIds = delFieldList.stream().map(GenTableField::getId).collect(Collectors.toList());
            tableFieldService.removeBatchByIds(fieldIds);
        }
    }
}
